{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Sequencing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This model uses the basal ganglia model to cycle through a sequence of five representations (i.e., A->B->C->D->E->A->...). The model incorporates a working memory component (state), which allows the basal ganglia to update that memory based on a set of condition/action mappings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Setup the environment\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "import nengo                \n",
    "from nengo import spa  # import spa related packages"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create the model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The model has parameters as described in the book. In Nengo 1.4 (book) separate 'Rules' and 'Sequence' classes were created, however, this is not needed in Nengo 2.0 since you can directly specify the rules using the built-in 'Actions' class in spa (semantic pointer architecutre) package. This class takes a string definition of the action as an input as shown in the code where '-->' is used to split the action into condition and effect, otherwise it is treated as having no condition and just effect.\n",
    "\n",
    "The syntax for creating an input function in Nengo 2.0 is also different from that in Nengo 1.4 mentioned in the book. The syntax for Nengo 2.0 which you will use here is spa.input(module=function). The first parameter 'module' refers to name of the module that you want to provide input to and the second parameter 'function' refers to the function to execute to generate inupts to that module. The functions should always return strings, which will then be parsed by the relevant vocabulary.\n",
    "\n",
    "In Nengo 1.4, a memory element for representing the `state` was created by using Buffer() as described in the book. However, in Nengo 2.0, you will have to use State() with feedback parameter set to 1 for creating a memory module capable of storing a vector over time.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Number of dimensions for the Semantic Pointers\n",
    "dimensions = 16\n",
    "\n",
    "# Make a model with the SPA network\n",
    "model = spa.SPA(label='Sequence')\n",
    "with model:\n",
    "    # Creating a working memory/cortical element \n",
    "    model.state = spa.State(dimensions=dimensions, feedback=1, feedback_synapse=0.01)\n",
    "    \n",
    "    # Specifying the action mappings (rules) for BG and Thal \n",
    "    actions = spa.Actions(\n",
    "        'dot(state, A) --> state = B',\n",
    "        'dot(state, B) --> state = C',\n",
    "        'dot(state, C) --> state = D',\n",
    "        'dot(state, D) --> state = E',\n",
    "        'dot(state, E) --> state = A'\n",
    "    )\n",
    "    \n",
    "    # Creating the BG and Thalamus components that confirm to the specified rules\n",
    "    model.BG = spa.BasalGanglia(actions=actions)    \n",
    "    model.thal = spa.Thalamus(model.BG)             \n",
    "    \n",
    "    # Function that provides the model with an initial input semantic pointer.\n",
    "    def start(t):\n",
    "        if t < 0.1:     # Duration of the initial input = 0.1\n",
    "            return 'D'\n",
    "        else:\n",
    "            return '0'\n",
    "        \n",
    "    # Input\n",
    "    model.input = spa.Input(state=start)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Import the nengo_gui visualizer to run and visualize the model.\n",
    "from nengo_gui.ipython import IPythonViz\n",
    "IPythonViz(model, \"ch7-spa-sequence.py.cfg\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Press the play button in the visualizer to run the simulation. You should see the graphs as shown in the figure below.\n",
    "\n",
    "The graph on the top-left shows the semantic pointer representation of the values stored in the `state` ensemble. The graph on the bottom-right shows the current transition or the action being executed, and the graph on the top-right shows the utility (similarity) of the current basal ganglia input (i.e., `state`) with the possible vocabulary vectors.\n",
    "\n",
    "The book describes that the results of the model can be seen through the visualizer in Nengo 1.4 GUI which has a \"Utility\" box and the \"Rules\" box. Note that the bottom-right graph shows the same information as seen in the \"Rules\" box and top-right graph shows the same information as seen in the \"Utility\" box."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from IPython.display import Image\n",
    "Image(filename='ch7-spa-sequence.png')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
